'MediaWiki\\Session\\UserInfo' => __DIR__ . '/includes/session/UserInfo.php',
'MediaWiki\\ShellDisabledError' => __DIR__ . '/includes/exception/ShellDisabledError.php',
'MediaWiki\\Shell\\Command' => __DIR__ . '/includes/shell/Command.php',
+ 'MediaWiki\\Shell\\CommandFactory' => __DIR__ . '/includes/shell/CommandFactory.php',
'MediaWiki\\Shell\\Result' => __DIR__ . '/includes/shell/Result.php',
'MediaWiki\\Shell\\Shell' => __DIR__ . '/includes/shell/Shell.php',
'MediaWiki\\Site\\MediaWikiPageNameNormalizer' => __DIR__ . '/includes/site/MediaWikiPageNameNormalizer.php',
use GlobalVarConfig;
use Hooks;
use IBufferingStatsdDataFactory;
+use MediaWiki\Shell\CommandFactory;
use Wikimedia\Rdbms\LBFactory;
use LinkCache;
use Wikimedia\Rdbms\LoadBalancer;
return $this->getService( 'ReadOnlyMode' );
}
+ /**
+ * @since 1.30
+ * @return CommandFactory
+ */
+ public function getShellCommandFactory() {
+ return $this->getService( 'ShellCommandFactory' );
+ }
+
///////////////////////////////////////////////////////////////////////////
// NOTE: When adding a service getter here, don't forget to add a test
// case for it in MediaWikiServicesTest::provideGetters() and in
use MediaWiki\Linker\LinkRendererFactory;
use MediaWiki\Logger\LoggerFactory;
use MediaWiki\MediaWikiServices;
+use MediaWiki\Shell\CommandFactory;
return [
'DBLoadBalancerFactory' => function ( MediaWikiServices $services ) {
);
},
+ 'ShellCommandFactory' => function ( MediaWikiServices $services ) {
+ $config = $services->getMainConfig();
+
+ $limits = [
+ 'time' => $config->get( 'MaxShellTime' ),
+ 'walltime' => $config->get( 'MaxShellWallClockTime' ),
+ 'memory' => $config->get( 'MaxShellMemory' ),
+ 'filesize' => $config->get( 'MaxShellFileSize' ),
+ ];
+ $cgroup = $config->get( 'ShellCgroup' );
+
+ $factory = new CommandFactory( $limits, $cgroup );
+ $factory->setLogger( LoggerFactory::getInstance( 'exec' ) );
+
+ return $factory;
+ },
+
///////////////////////////////////////////////////////////////////////////
// NOTE: When adding a service here, don't forget to add a getter function
// in the MediaWikiServices class. The convenience getter should just call
private $everExecuted = false;
/** @var string|false */
- private $cGroup = false;
+ private $cgroup = false;
/**
* Constructor. Don't call directly, instead use Shell::command()
/**
* Sets execution limits
*
- * @param array $limits Optional array with limits(filesize, memory, time, walltime).
+ * @param array $limits Associative array of limits. Keys (all optional):
+ * filesize (for ulimit -f), memory, time, walltime.
* @return $this
*/
public function limits( array $limits ) {
/**
* Sets cgroup for this command
*
- * @param string|false $cgroup
+ * @param string|false $cgroup Absolute file path to the cgroup, or false to not use a cgroup
* @return $this
*/
public function cgroup( $cgroup ) {
- $this->cGroup = $cgroup;
+ $this->cgroup = $cgroup;
return $this;
}
escapeshellarg(
"MW_INCLUDE_STDERR=" . ( $this->useStderr ? '1' : '' ) . ';' .
"MW_CPU_LIMIT=$time; " .
- 'MW_CGROUP=' . escapeshellarg( $this->cGroup ) . '; ' .
+ 'MW_CGROUP=' . escapeshellarg( $this->cgroup ) . '; ' .
"MW_MEM_LIMIT=$mem; " .
"MW_FILE_SIZE_LIMIT=$filesize; " .
"MW_WALL_CLOCK_LIMIT=$wallTime; " .
--- /dev/null
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+namespace MediaWiki\Shell;
+
+use Psr\Log\LoggerAwareTrait;
+use Psr\Log\NullLogger;
+
+/**
+ * Factory facilitating dependency injection for Command
+ *
+ * @since 1.30
+ */
+class CommandFactory {
+ use LoggerAwareTrait;
+
+ /** @var array */
+ private $limits;
+
+ /** @var string|bool */
+ private $cgroup;
+
+ /**
+ * Constructor
+ *
+ * @param array $limits See {@see Command::limits()}
+ * @param string|bool $cgroup See {@see Command::cgroup()}
+ */
+ public function __construct( array $limits, $cgroup ) {
+ $this->limits = $limits;
+ $this->cgroup = $cgroup;
+ $this->setLogger( new NullLogger() );
+ }
+
+ /**
+ * Instantiates a new Command
+ *
+ * @return Command
+ */
+ public function create() {
+ $command = new Command();
+ $command->setLogger( $this->logger );
+
+ return $command
+ ->limits( $this->limits )
+ ->cgroup( $this->cgroup );
+ }
+}
namespace MediaWiki\Shell;
-use MediaWiki\Logger\LoggerFactory;
use MediaWiki\MediaWikiServices;
/**
// treat it as a list of arguments
$args = reset( $args );
}
- $command = new Command();
- $config = MediaWikiServices::getInstance()->getMainConfig();
-
- $limits = [
- 'time' => $config->get( 'MaxShellTime' ),
- 'walltime' => $config->get( 'MaxShellWallClockTime' ),
- 'memory' => $config->get( 'MaxShellMemory' ),
- 'filesize' => $config->get( 'MaxShellFileSize' ),
- ];
- $command->limits( $limits );
- $command->cgroup( $config->get( 'ShellCgroup' ) );
- $command->setLogger( LoggerFactory::getInstance( 'exec' ) );
+ $command = MediaWikiServices::getInstance()
+ ->getShellCommandFactory()
+ ->create();
return $command->params( $args );
}
use MediaWiki\Services\DestructibleService;
use MediaWiki\Services\SalvageableService;
use MediaWiki\Services\ServiceDisabledException;
+use MediaWiki\Shell\CommandFactory;
/**
* @covers MediaWiki\MediaWikiServices
'MainObjectStash' => [ 'MainObjectStash', BagOStuff::class ],
'MainWANObjectCache' => [ 'MainWANObjectCache', WANObjectCache::class ],
'LocalServerObjectCache' => [ 'LocalServerObjectCache', BagOStuff::class ],
- 'VirtualRESTServiceClient' => [ 'VirtualRESTServiceClient', VirtualRESTServiceClient::class ]
+ 'VirtualRESTServiceClient' => [ 'VirtualRESTServiceClient', VirtualRESTServiceClient::class ],
+ 'ShellCommandFactory' => [ 'ShellCommandFactory', CommandFactory::class ],
];
}
--- /dev/null
+<?php
+
+use MediaWiki\Shell\CommandFactory;
+use Psr\Log\NullLogger;
+use Wikimedia\TestingAccessWrapper;
+
+/**
+ * @group Shell
+ */
+class CommandFactoryTest extends PHPUnit_Framework_TestCase {
+ /**
+ * @covers MediaWiki\Shell\CommandFactory::create
+ */
+ public function testCreate() {
+ $logger = new NullLogger();
+ $cgroup = '/sys/fs/cgroup/memory/mygroup';
+ $limits = [
+ 'filesize' => 1000,
+ 'memory' => 1000,
+ 'time' => 30,
+ 'walltime' => 40,
+ ];
+
+ $factory = new CommandFactory( $limits, $cgroup );
+ $factory->setLogger( $logger );
+ $command = $factory->create();
+
+ $wrapper = TestingAccessWrapper::newFromObject( $command );
+ $this->assertSame( $logger, $wrapper->logger );
+ $this->assertSame( $cgroup, $wrapper->cgroup );
+ $this->assertSame( $limits, $wrapper->limits );
+ }
+}